package simulator.labyrinth;

import java.util.ArrayList;

//import simulator.labyrinth.Labyrinth;
import simulator.position.Point;
import simulator.position.Position;

import Robot.SensorColour;

public class BarCode {
	private int number;
	public double orientation;
	public Point pos;
	private final static int[] validCodes = { 5, 9, 13, 15, 19, 25, 37, 55 };

	public BarCode(int number,Position position){
		this.number = number;
		if (!isValidCode(number))
        	this.number = calculateInverseNumber(number);
		
		if(Double.compare(Math.round((position.getOrientation() % 180) + 180) % 180, 45) < 0 || Double.compare(Math.round((position.getOrientation() % 180) + 180) % 180, 135) > 0)
			this.orientation = 0;
		else
			this.orientation = Math.PI/2;
		pos = Labyrinth.getStartPointOfSquare(position.getPoint());
	}
	
    public static int calculateInverseNumber(int number) {
    	int rest = number;
		int result = 0;
		for(int i = 5; i >=0; i--)
		{
			int bit = (int) (rest / Math.pow(2, i));
			rest -= bit*Math.pow(2, i); 
			result += (int) (Math.pow(2, (5-i))*bit);
		}
		return result;
    }
	
	public ArrayList<Line> getLines(){
	    if(number != 0){
	        int rest = number;
	        ArrayList<Line> lines = new ArrayList<Line>(8);
	        lines.add(new Line(new Point(pos.getX()+13*Math.sin(orientation),pos.getY()+13*Math.cos(orientation)),
	                new Point(pos.getX()+13*Math.sin(orientation)+Math.cos(orientation)*40,pos.getY()+40*Math.sin(orientation)+13*Math.cos(orientation)),
	                SensorColour.BLACK));
	        int modulo = (int) Math.pow(2, 5);
	        for(int i = 5; i>=0; i--){

	            int result = rest/modulo;
	            SensorColour color = SensorColour.BLACK;
	            if(result == 1){
	                color = SensorColour.WHITE;
	                rest = rest-modulo;
	            }
	            Line line = new Line(new Point(pos.getX()+(15+2*i)*Math.sin(orientation),pos.getY()+(15+2*i)*Math.cos(orientation)),
	                    new Point(pos.getX()+(15+2*i)*Math.sin(orientation)+Math.cos(orientation)*40,pos.getY()+40*Math.sin(orientation)+(15+2*i)*Math.cos(orientation)),
	                    color);
	            lines.add(line);

	            modulo /= 2;
	        }
	        lines.add(new Line(new Point(pos.getX()+27*Math.sin(orientation),pos.getY()+27*Math.cos(orientation)),
	                new Point(pos.getX()+27*Math.sin(orientation)+Math.cos(orientation)*40,pos.getY()+40*Math.sin(orientation)+27*Math.cos(orientation)),
	                SensorColour.BLACK));
	        return lines;
	    }
	    else
	        return new ArrayList<Line>();
	}
	
	public Action getAction(){
		//TODO: terug juiste waarden ingeven
		switch (number) {
			case 1:
				return Action.TURN_LEFT;
			case 9:
				return Action.TURN_RIGHT;
			case 13:
				return Action.CHECKPOINT;
			case 17:
				return Action.PLAY_TUNE;
			case 19:
				return Action.WAIT;
			case 25:
				return Action.DRIVE_SLOW;
				
			case 37:
				return Action.DRIVE_FAST;
				
			case 47: //55:
				return Action.FINISH;
				
				
			default:
				return Action.NONE;
			}
	}
	
    public static boolean isValidCode(int number)
    {
    	for (int i = 0; i < validCodes.length; i++)
            if (validCodes[i] == number)
                return true;
    	return false;
    }

    public int getNumber() {
		return number;
	}
}
